(* matrice.ml
 *
 * This file is part of camEngine
 * 
 * camEngine - A 3d motor for ocaml
 * Copyright (C) 2009 DAVY Guillaume <davyg2@gmail.com>
 *
 * camEngine is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * camEngine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with camEngine.  If not, see <http://www.gnu.org/licenses/>.
 *)

open Array;;
open Vec3d;;
open Oo;;

type t=float
class matrice4 = object (self)
	val mutable mat = (Array.create_matrix 4 4 0.)
	
	method fill_diagC (a:t) =
		for i=0 to 3 do
			mat.(i).(i) <- a;
		done;
	
	method fill_diagA (a:(t array)) =
		for i=0 to 3 do
			mat.(i).(i) <- a.(i);
		done;
	
	method print =
		for i=0 to 3 do
			for j=0 to 3 do
			print_float mat.(i).(j);
			print_string "\t";
			done;
			print_string "\n";
		done;
	
	method put i j a =
		mat.(i).(j) <- a;
	
	method get i j =
		mat.(i).(j);
	
	method add (a:matrice4) =
		for i=0 to 3 do
			for j=0 to 3 do
				mat.(i).(j) <- mat.(i).(j) +. (a#get i j);
			done;
		done;
		
	method get_mat =
		let m = Array.create_matrix 4 4 0. in
		for i=0 to 3 do
			for j=0 to 3 do
				m.(i).(j) <- mat.(i).(j);
			done;
		done;
		m;
	
	method mul (arg:matrice4) =
		let a = self#get_mat in
		let b = arg#get_mat in
		for i=0 to 3 do
			for j=0 to 3 do
				mat.(i).(j) <- 0.;
				for k=0 to 3 do
					mat.(i).(j) <- mat.(i).(j) +. (a.(i).(k) *. b.(k).(j));
				done;
			done;
		done;
	
	method mulVec (arg:vec3d) =
		let r = Array.create 4 0. in
		let a = Array.create 4 1. in
		a.(0) <- arg#get_x;
		a.(1) <- arg#get_y;
		a.(2) <- arg#get_z;
		for i=0 to 3 do
			for k=0 to 3 do
				r.(i) <- r.(i) +. (mat.(i).(k) *. a.(k));
			done;
		done;
		arg#set_x r.(0);
		arg#set_y r.(1);
		arg#set_z r.(2);
	
	method reverse =
		mat.(0).(3) <- -. mat.(0).(3);
		mat.(1).(3) <- -. mat.(1).(3);
		mat.(2).(3) <- -. mat.(2).(3);
		
	initializer
		self#fill_diagC 1.;
end;;

